package com.bifrost.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.bifrost.constant.InventoryType;
import com.bifrost.constant.ShippingType;
import com.bifrost.entity.*;
import com.bifrost.event.CartUpdateEvent;
import com.bifrost.common.model.ResultModel;
import com.bifrost.model.cart.CartItemResult;
import com.bifrost.model.cart.CartResult;
import com.bifrost.repository.*;
import com.bifrost.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author rangjf
 * @date 2017/11/6
 */
@Service
public class ShoppingCartServiceImpl implements ShoppingCartService, ApplicationContextAware {

    private Logger logger = LoggerFactory.getLogger(ShoppingCartServiceImpl.class);

    @Autowired
    ShoppingCartRepository cartRepository;
    @Autowired
    ShoppingCartItemRepository cartItemRepository;
    @Autowired
    ProductSkuRepository productSkuRepository;
    @Autowired
    SkuServicePriceRepository skuServicePriceRepository;
    @Autowired
    ProductServiceRepository productServiceRepository;
    @Autowired
    SkuMediaMapService skuMediaMapService;
    @Autowired
    ProductSkuService skuService;
    @Autowired
    StoreService storeService;
    @Autowired
    InventoryService inventoryService;

    protected ApplicationContext applicationContext;

    @Autowired
    JedisService jedisService;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 加入购物车
     *
     * @param customer
     * @param skuId
     * @param quantity
     * @param hasService        是否有服务
     * @param skuServicePriceId skuServicePriceId
     * @param serviceMerchantId 服务门店Id
     * @return Map
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultModel addToCarts(Customer customer, Long skuId, Long quantity,
                                  String hasService, String skuServicePriceId, Long serviceMerchantId) {

        ProductSku sku = productSkuRepository.findOne(skuId);
        if (!skuService.isAvailable(sku)) {
            return ResultModel.error("库存不足");
        }
        MerchantStore merchantStore = storeService.getMerchantStore(sku.getProduct().getMerchantId());
        ShoppingCart dbCart = cartRepository.getByCustomerAndMerchantStore(customer, merchantStore);
        if (dbCart == null) {
            dbCart = new ShoppingCart();
            dbCart.setCustomer(customer);
            dbCart.setCreatedTimestamp(new Date());
            dbCart.setUpdatedTimestamp(new Date());
            dbCart.setMerchantStore(merchantStore);
            dbCart = cartRepository.save(dbCart);
        }
        //购物车是否已经存在sku
        ShoppingCartItem dbCartItem = cartItemRepository.getByShoppingCartAndSkuId(dbCart, skuId);
        if (dbCartItem != null) {
            Long dbQuantity = dbCartItem.getItemQuantity();
            if (InventoryType.CHECK_QUANTITY.equalsIgnoreCase(sku.getInventoryType()) && (dbQuantity + quantity > sku.getQuantityAvailable())) {
                return ResultModel.error("库存不足");
            }
            dbCartItem.setItemQuantity(dbQuantity + quantity);
            return ResultModel.ok("加入购物车成功");
        }
        ShoppingCartItem cartItem = new ShoppingCartItem();
        cartItem.setSkuId(skuId);
        cartItem.setItemQuantity(quantity);
        cartItem.setUpdatedTimestamp(new Date());
        cartItem.setShoppingCart(dbCart);
        //TODO sku是否有安装服务
        cartItemRepository.save(cartItem);
        return ResultModel.ok("加入购物车成功");
    }

    /**
     * 加入购物车
     *
     * @param store
     * @param customer
     * @param skuId
     * @param quantity
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultModel addToCartsByStore(MerchantStore store, Customer customer, Long skuId, Long quantity) {
        ProductSku sku = productSkuRepository.findOne(skuId);
        if (!skuService.isAvailable(sku)) {
            return ResultModel.error("库存不足");
        }
        ShoppingCart cart = cartRepository.getByCustomerAndMerchantStore(customer, store);
        if(cart == null){
            cart = new ShoppingCart();
            cart.setCustomer(customer);
            cart.setCreatedTimestamp(new Date());
            cart.setUpdatedTimestamp(new Date());
            cart.setMerchantStore(store);
            cart = cartRepository.save(cart);
        }
        ShoppingCartItem dbCartItem = cartItemRepository.getByShoppingCartAndSkuId(cart, skuId);
        if (dbCartItem != null) {
            Long dbQuantity = dbCartItem.getItemQuantity();
            if (InventoryType.CHECK_QUANTITY.equalsIgnoreCase(sku.getInventoryType()) && (dbQuantity + quantity > sku.getQuantityAvailable())) {
                return ResultModel.error("库存不足");
            }
            dbCartItem.setItemQuantity(dbQuantity + quantity);
            publishCartUpdateEvent(store, customer);
            return ResultModel.ok("加入购物车成功");
        }
        ShoppingCartItem cartItem = new ShoppingCartItem();
        cartItem.setSkuId(skuId);
        cartItem.setItemQuantity(quantity);
        cartItem.setUpdatedTimestamp(new Date());
        cartItem.setShoppingCart(cart);
        cartItemRepository.save(cartItem);
        publishCartUpdateEvent(store, customer);
        return ResultModel.ok("加入购物车成功");
    }

    /**
     * 获取购物车数量
     *
     * @param customer
     * @return List
     */
    @Override
    public Long getCartsQuantity(Customer customer) {
        List<ShoppingCart> cartList = cartRepository.getByCustomer(customer);
        if (cartList != null && !cartList.isEmpty()) {
            Long quantity = 0L;
            for (ShoppingCart cart : cartList) {
                Long dbQuantity = cartItemRepository.sumCartQuantity(cart.getShopppingCartId());
                if (dbQuantity != null) {
                    quantity += dbQuantity;
                }
            }
            return quantity;
        }
        return null;
    }

    /**
     * 获取购物车数量
     *
     * @param store
     * @param customer
     * @return List
     */
    @Override
    public Long getCartsQuantityByStore(MerchantStore store, Customer customer) {
        if(customer != null && store != null) {
            String quantityKey = String.
                    format("customer:carts:quantity:%s:%s", customer.getCustomerId(), store.getMerchantId());
            String result = jedisService.get(quantityKey);
            if (StringUtils.isEmpty(result)) {
                ShoppingCart cart = cartRepository.getByCustomerAndMerchantStore(customer, store);
                if (cart != null) {
                    Long quantity = cartItemRepository.sumCartQuantity(cart.getShopppingCartId());
                    jedisService.set(quantityKey, quantity.toString());
                    return quantity;
                }
                return null;
            }
            return Long.valueOf(result);
        }
        return null;
    }

    /**
     * 获取购物车信息
     *
     * @param customer customer
     * @return Map
     */
    @Override
    public List<CartResult> getCarts(Customer customer) {
        List<ShoppingCart> cartList = cartRepository.getByCustomer(customer);
        if (CollectionUtils.isNotEmpty(cartList)) {
            return cartList.stream().map(shoppingCart -> convertCartToCartResult(shoppingCart)).collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 获取购物车信息
     * 仅用于重百商城：List.size <= 1
     *
     * @param customer
     * @param store
     * @return
     */
    @Override
    public List<CartResult> getCartsByStore(Customer customer, MerchantStore store) {
        try {
            if(customer != null && store != null){
                String cartsKey =
                        String.format("customer:carts:cart:%s:%s", customer.getCustomerId(), store.getMerchantId());
                String result = jedisService.get(cartsKey);
                if (StringUtils.isEmpty(result)) {
                    ShoppingCart shoppingCart = cartRepository.getByCustomerAndMerchantStore(customer, store);
                    if (shoppingCart != null) {
                        List<CartResult> carts = new ArrayList<>();
                        carts.add(convertCartToCartResult(shoppingCart));
                        jedisService.set(cartsKey, JSON.toJSONString(carts, SerializerFeature.DisableCircularReferenceDetect));
                        return carts;
                    }
                    return null;
                }
                List<CartResult> cartResultList = new ArrayList<>();
                JSONArray arrays = JSON.parseArray(result);
                for (Object array : arrays) {
                    JSONObject obj = JSON.parseObject(array.toString());
                    CartResult cartResult = new CartResult();
                    cartResult.setCartId(obj.getLong("cartId"));
                    cartResult.setStoreId(obj.getLong("storeId"));
                    cartResult.setStoreName(obj.getString("storeName"));
                    cartResult.setItems(JSON.parseArray(obj.getString("items"), CartItemResult.class));
                    cartResultList.add(cartResult);
                }
                return cartResultList;
            }
        }catch (Exception e){
            logger.error("carts data has error");
        }
        return null;
    }

    private CartResult convertCartToCartResult(ShoppingCart shoppingCart){
        MerchantStore store = shoppingCart.getMerchantStore();
        CartResult cart = new CartResult();
        cart.setCartId(shoppingCart.getShopppingCartId());
        cart.setStoreId(store.getMerchantId());
        cart.setStoreName(store.getStoreName());
        cart.setItems(new ArrayList<>());
        List<ShoppingCartItem> cartItemList = shoppingCart.getShoppingCartItems();
        if (cartItemList != null && !cartItemList.isEmpty()) {
            cartItemList.forEach(shoppingCartItem -> {
                CartItemResult item = new CartItemResult();
                ProductSku sku = skuService.getSkuById(shoppingCartItem.getSkuId());
                ProductSku defaultSku = sku.getProduct().getDefaultSku();
                if (!skuService.isAvailable(sku)) {
                    item.setAvailable(false);
                    item.setUnAvailableReason("库存不足");
                } else {
                    item.setAvailable(true);
                }
                item.setCartItemId(shoppingCartItem.getShoppingCartItemId());
                item.setSkuId(sku.getSkuId());
                item.setStock(inventoryService.getInventoryBySkuId(sku.getSkuId()));
                item.setProductId(sku.getProduct().getProductId());
                item.setName(sku.getSkuName());
                item.setSkuAssociation(skuService.getSkuGiftAndService(sku));
                item.setUrl(skuService.getSkuDefaultMeda(defaultSku));
                item.setPrice(sku.getSalePrice());
                item.setQuantity(shoppingCartItem.getItemQuantity());
                String shippingType = sku.getFulfillmentType();
                if (StringUtils.isNotEmpty(shippingType)) {
                    if (ShippingType.DELIVERY.equalsIgnoreCase(shippingType)) {
                        item.setShippingType(ShippingType.DELIVERY);
                    } else if (ShippingType.SELF_DELIVERY.equalsIgnoreCase(shippingType)) {
                        item.setShippingType(ShippingType.SELF_DELIVERY);
                    } else if (ShippingType.BOTH.equalsIgnoreCase(shippingType)) {
                        item.setShippingType(ShippingType.BOTH);
                    } else {
                        item.setShippingType(ShippingType.DELIVERY);
                    }
                } else {
                    item.setShippingType(ShippingType.DELIVERY);
                }

                cart.getItems().add(item);
            });
        }
        return cart;
    }

    /**
     * 修改购物车
     *
     * @param customer
     * @param store
     * @param cartItemId
     * @param quantity   购物车商品数量
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCarts(Customer customer, MerchantStore store, @RequestParam Long cartItemId, @RequestParam Long quantity) {
        if(customer != null && store != null) {
            ShoppingCartItem cartItem = cartItemRepository.findOne(cartItemId);
            if (cartItem != null) {
                ProductSku sku = skuService.getSkuById(cartItem.getSkuId());
                if (skuService.isAvailable(sku)) {
                    if (InventoryType.CHECK_QUANTITY.equalsIgnoreCase(sku.getInventoryType()) && quantity > sku.getQuantityAvailable()) {
                        return false;
                    }
                    cartItemRepository.updateCartItemById(quantity, cartItemId);
                    publishCartUpdateEvent(store, customer);
                    return true;
                } else {
                    return false;
                }
            }
            return false;
        }
        return false;
    }

    /**
     * 移除购物车
     *
     * @param customer
     * @param store
     * @param cartItemIds 购物车itemIds数组
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteCarts(Customer customer, MerchantStore store, String[] cartItemIds) {
        if(customer != null && store != null) {
            for (String id : cartItemIds) {
                ShoppingCartItem item = cartItemRepository.findOne(Long.parseLong(id));
                ShoppingCart cart = item.getShoppingCart();
                cartItemRepository.delete(Long.parseLong(id));
                Long number = cartItemRepository.countByShoppingCart(cart);
                if (number == 0L) {
                    cartRepository.delete(cart.getShopppingCartId());
                }
            }
            publishCartUpdateEvent(store, customer);
            return true;
        }
        return false;
    }

    /**
     * 删除购物车中指定商品
     *
     * @param customer
     * @param store
     * @param cartId
     * @param skus
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean deleteSkusByCart(Customer customer, MerchantStore store, Long cartId, List<Long> skus) {
        if (customer != null && store != null) {
            if (cartId != null && skus != null && !skus.isEmpty()) {
                ShoppingCart cart = cartRepository.findOne(cartId);
                List<ShoppingCartItem> items = cart.getShoppingCartItems();
                items.removeIf(shoppingCartItem -> {
                    return skus.contains(shoppingCartItem.getSkuId());
                });
                if (items == null || items.isEmpty()) {
                    cartRepository.delete(cartId);
                } else {
                    cart.setShoppingCartItems(items);
                    cart.setUpdatedTimestamp(new Date());
                    cartRepository.saveAndFlush(cart);
                }
                publishCartUpdateEvent(store, customer);
                return true;
            }
            return false;
        }
        return false;
    }

    private void publishCartUpdateEvent(MerchantStore store, Customer customer){
        CartUpdateEvent event = new CartUpdateEvent(store.getMerchantId(), customer.getCustomerId());
        applicationContext.publishEvent(event);
    }

}
